﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using IPC.Communication.Framework.Core;
using IPC.Communication.Framework.BasicFramework;

namespace IPC.Communication.Framework.MQTT
{
    public class MqttSession : ISessionContext
    {
	    private object objLock = new object();

	    public IPEndPoint EndPoint
	    {
		    get;
		    set;
	    }

	    public string ClientId
	    {
		    get;
		    set;
	    }

	    public DateTime ActiveTime
	    {
		    get;
		    set;
	    }

	    public DateTime OnlineTime
	    {
		    get;
		    private set;
	    }

	    public TimeSpan ActiveTimeSpan
	    {
		    get;
		    set;
	    }

	    internal Socket MqttSocket
	    {
		    get;
		    set;
	    }

	    private List<string> Topics
	    {
		    get;
		    set;
	    }

	    public string UserName
	    {
		    get;
		    set;
	    }

	    public string Protocol
	    {
		    get;
		    private set;
	    }

	    public object Tag
	    {
		    get;
		    set;
	    }

	    public bool ForbidPublishTopic
	    {
		    get;
		    set;
	    }

	    public MqttSession(IPEndPoint endPoint, string protocol)
	    {
		    Topics = new List<string>();
		    ActiveTime = DateTime.Now;
		    OnlineTime = DateTime.Now;
		    ActiveTimeSpan = TimeSpan.FromSeconds(1000000.0);
		    EndPoint = endPoint;
		    Protocol = protocol;
	    }

	    public bool IsClientSubscribe(string topic)
	    {
		    bool result = false;
		    lock (objLock)
		    {
			    result = Topics.Contains(topic);
		    }
		    return result;
	    }

	    public string[] GetTopics()
	    {
		    lock (objLock)
		    {
			    return Topics.ToArray();
		    }
	    }

	    public void AddSubscribe(string topic)
	    {
		    lock (objLock)
		    {
			    if (!Topics.Contains(topic))
			    {
				    Topics.Add(topic);
			    }
		    }
	    }

	    public void AddSubscribe(string[] topics)
	    {
		    if (topics != null)
		    {
			    lock (objLock)
			    {
				    for (int i = 0; i < topics.Length; i++)
				    {
					    if (!Topics.Contains(topics[i]))
					    {
						    Topics.Add(topics[i]);
					    }
				    }
			    }
		    }
	    }

	    public void RemoveSubscribe(string topic)
	    {
		    lock (objLock)
		    {
			    if (Topics.Contains(topic))
			    {
				    Topics.Remove(topic);
			    }
		    }
	    }

	    public void RemoveSubscribe(string[] topics)
	    {
		    if (topics != null)
		    {
			    lock (objLock)
			    {
				    for (int i = 0; i < topics.Length; i++)
				    {
					    if (Topics.Contains(topics[i]))
					    {
						    Topics.Remove(topics[i]);
					    }
				    }
			    }
		    }
	    }

	    public string GetSessionOnlineInfo()
	    {
		    StringBuilder stringBuilder = new StringBuilder(ToString());
		    stringBuilder.Append(" [" + SoftBasic.GetTimeSpanDescription(DateTime.Now - OnlineTime) + "]");
		    return stringBuilder.ToString();
	    }

	    public override string ToString()
	    {
            StringBuilder stringBuilder = new StringBuilder(String.Format("{0} Session[IP:{1}]", Protocol, EndPoint));
		    if (!string.IsNullOrEmpty(ClientId))
		    {
			    stringBuilder.Append(" [ID:" + ClientId + "]");
		    }
		    if (!string.IsNullOrEmpty(UserName))
		    {
			    stringBuilder.Append(" [Name:" + UserName + "]");
		    }
		    return stringBuilder.ToString();
	    }
    }
}
